package com.jx.gocomtask.webservice.service.impl;

import com.jx.gocomtask.webservice.DTO.*;
import com.jx.gocomtask.webservice.DTO.query.MessageQuery;
import com.jx.gocomtask.webservice.DTO.query.PageDTO;
import com.jx.gocomtask.webservice.entity.*;
import com.jx.gocomtask.webservice.repository.ExtTaskMessageHistoryRepository;
import com.jx.gocomtask.webservice.repository.ExtTaskMessageReplyRepository;
import com.jx.gocomtask.webservice.repository.ExtTaskMessageRepository;
import com.jx.gocomtask.webservice.repository.ExtTaskRelationRepository;
import com.jx.gocomtask.webservice.repository.service.ExtTaskMessageDao;
import com.jx.gocomtask.webservice.service.ExtTaskMessageService;
import com.jx.gocomtask.webservice.service.ExtTaskSearchHistoryService;
import com.jx.gocomtask.webservice.service.GroupService;
import com.jx.gocomtask.webservice.service.Route;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import phoenics.common.BaseData.BaseErrorCode;
import phoenics.common.exception.NotFoundException;
import phoenics.common.exception.ParamsException;
import phoenics.common.exception.StatusException;

import javax.annotation.Resource;
import javax.persistence.criteria.*;
import javax.transaction.Transactional;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by LWD on 2017/8/7.
 */
@Service
public class ExtTaskMessageServiceImpl implements ExtTaskMessageService {
    @Resource(name="apiurl")
    String gocomeApiUrl;
    @Resource(name="serviceUrl")
    String serviceUrl;
    @Resource(name="serviceIosUrl")
    String serviceIosUrl;
    @Resource(name="serviceAndroidUrl")
    String serviceAndroidUrl;
    @Resource(name="defaultAppId")
    String defaultAppId;
    @Resource(name="defaultGroupAppId")
    String  defaultGroupAppId;
    @Autowired
    Route route;
    @Resource
    GroupService groupService;
    @Resource
    ExtTaskMessageRepository extTaskMessageRepository;
    @Resource
    ExtTaskSearchHistoryService extTaskSearchHistoryService;
    @Resource
    ExtTaskMessageReplyRepository extTaskMessageReplyRepository;
    @Resource
    ExtTaskMessageHistoryRepository extTaskMessageHistoryRepository;
    @Resource
    ExtTaskMessageDao extTaskMessageDao;
    @Resource
    ExtTaskRelationRepository extTaskRelationRepository;

    @Override
    public PageDTO<ExtTaskMessage> findAll(MessageQuery query, Pageable pageable) {
        Specification<ExtTaskMessage> specification = this.getSQL(query);

        Page<ExtTaskMessage> page = extTaskMessageRepository.findAll(specification, pageable);
        if(null != page && null != page.getContent() && page.getContent().size() > 0){
            for(ExtTaskMessage message : page.getContent())
                message.setIsRelation(1);
        }

        PageDTO<ExtTaskMessage> pageDTO = new PageDTO<>();
        pageDTO.elements = (List<ExtTaskMessage>)page.getContent();
        pageDTO.totalElements = (int) page.getTotalElements();
        pageDTO.index = page.getNumber();
        pageDTO.size = page.getSize();

        return pageDTO;
    }

    @Override
    public void relevance(String super_uuid, String child_uuid, Integer type) {
        ExtTaskMessage extTaskMessage_super = extTaskMessageRepository.findByUuid(super_uuid);
        ExtTaskMessage extTaskMessage_child = extTaskMessageRepository.findByUuid(child_uuid);
        ExtTaskRelation relation = extTaskRelationRepository.findByMessageIdAndRelationMessageId(extTaskMessage_super.getId(), extTaskMessage_child.getId());
        if(0 == type){
            if(null != relation)
                extTaskRelationRepository.delete(relation);
        }
        if(1 == type){
            if(null == relation) {
                ExtTaskRelation relationAdd = new ExtTaskRelation();
                relationAdd.setMessageId(extTaskMessage_super.getId());
                relationAdd.setRelationMessageId(extTaskMessage_child.getId());
                relationAdd.setRelationTime(new Timestamp(System.currentTimeMillis()));
                extTaskRelationRepository.save(relationAdd);
            }
        }
    }

    @Override
    public ExtTaskMessage findByUUID(String uuid, String userid) {
        ExtTaskMessage extTaskMessage_base = extTaskMessageRepository.findByUuid(uuid);
//        已删除状态不能获取
        if(extTaskMessage_base==null || extTaskMessage_base.getStatus().equals(TaskStatus.DELETE)){
            throw new NotFoundException();
        }
        String userName = "";
        if(extTaskMessage_base.getScope() == TaskScope.ALL)
            userName = "全体成员";
        else if(extTaskMessage_base.getScope() == TaskScope.OTHER && extTaskMessage_base.getExtTaskUser()!=null){
        	userName=extTaskMessage_base.getExtTaskUser().stream().map(user->user.getTaskUserName()).collect(Collectors.joining(","));
        }else{
            userName = extTaskMessage_base.getFromUserTrueName();
        }
        extTaskMessage_base.setExtTaskUserName(userName);
        extTaskMessage_base.setIos(serviceIosUrl);
        extTaskMessage_base.setUrl(serviceUrl);
        extTaskMessage_base.setAndroid(serviceAndroidUrl);
        extTaskMessage_base.setFromUserTrueName(route.takeUserInfo(extTaskMessage_base.getFromUserTrueName()));
        String groupName = null;
        try{
            groupName = groupService.findByGuId(extTaskMessage_base.getGroup()).getGroupname();
        }catch (Exception e){
            groupName = null;
        }
        extTaskMessage_base.setGroupName(groupName);

//        ex
        this.setRole(userid, extTaskMessage_base);
        this.setStatus(userid, extTaskMessage_base);

//        获取关联任务
        MessageQuery query = new MessageQuery();
        query.msgUUID = extTaskMessage_base.getUuid();
        extTaskMessage_base.setRelationCount(this.findCount(query));
        return extTaskMessage_base;
    }

    public Long findCount(MessageQuery query) {

        Specification<ExtTaskMessage> specification = this.getSQL(query);

        Long count = extTaskMessageRepository.count(specification);

        return count;
    }

    public Specification<ExtTaskMessage> getSQL(MessageQuery query){
        Specification<ExtTaskMessage> specification = new Specification<ExtTaskMessage>() {
            @Override
            public Predicate toPredicate(Root<ExtTaskMessage> root,
                                         CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.notEqual(root.get("status"), TaskStatus.DELETE));
                if(StringUtils.isNotEmpty(query.group))
                    predicates.add(criteriaBuilder.equal(root.get("group"), query.group));
                if(null != query.msgUUID) {
                    ExtTaskMessage message = extTaskMessageRepository.findByUuid(query.msgUUID);
//                    获取关联任务
                    List<ExtTaskRelation> relationList = null;
                    if(null != message)
                        relationList = extTaskRelationRepository.findByMessageId(message.getId());

                    List<Long> c_list = new LinkedList<>();
                    if(null != relationList && relationList.size() > 0) {
                        for (ExtTaskRelation relation : relationList) {
                            c_list.add(relation.getRelationMessageId());
                        }
                    }else{
                        c_list.add(0L);
                    }
                    Iterator iterator = c_list.iterator();
                    CriteriaBuilder.In in = criteriaBuilder.in(root.get("id"));
                    while (iterator.hasNext()) {
                        in.value(iterator.next());
                    }
                    predicates.add(in);

                }
//                添加上下文过滤
                if(null != query.source) {
                    predicates.add(criteriaBuilder.lt(root.get("contextFlag"), 10));
                    predicates.add(criteriaBuilder.equal(root.get("source"), query.source));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return specification;
    }

    @Override
    public ExtTaskMessage updateByUUID(String uuid, String userid, TaskBody taskBody) {
        ExtTaskMessage extTaskMessage_base = this.findByUUID(uuid, userid);
        if (extTaskMessage_base == null) {
            throw new ParamsException();
        }
        if(extTaskMessage_base.getStatus().equals(TaskStatus.OVER) ||
                extTaskMessage_base.getStatus().equals(TaskStatus.FINISHED)  ||
                extTaskMessage_base.getStatus().equals(TaskStatus.REFUSE)  ||
                extTaskMessage_base.getStatus().equals(TaskStatus.DELETE) )
            throw new ParamsException(BaseErrorCode.SERVER_ERROR, extTaskMessage_base.getStatus().getDescTittle().replace("提醒", ""));
        Boolean isUpdate = false;
//        操作人验证
        if (!userid.equals(extTaskMessage_base.getFromUser())) {
            throw new StatusException(401, "无权进行此次操作");
        }
        if (null != taskBody.getContent() && !taskBody.getContent().equals(extTaskMessage_base.getContent())) {
            extTaskMessage_base.setContent(taskBody.getContent());
            isUpdate = true;
        }
        
        if (null != taskBody.getExecPlan() &&taskBody.getExecPlan() != extTaskMessage_base.getExecPlan()) {
            extTaskMessage_base.setExecPlan(taskBody.getExecPlan());
            isUpdate = true;
        }
        if (null != taskBody.getIsRemind()  &&taskBody.getIsRemind() != extTaskMessage_base.getIsRemind()) {
            extTaskMessage_base.setIsRemind(taskBody.getIsRemind());
            isUpdate = true;
        }
        if (null != taskBody.getDeadline() ) {
            extTaskMessage_base.setDeadline(taskBody.getDeadline());
            isUpdate = true;
        }
        if (null != taskBody.getIsRepeat()  &&taskBody.getIsRepeat() != extTaskMessage_base.getIsRepeat()) {
            extTaskMessage_base.setIsRepeat(taskBody.getIsRepeat());
            isUpdate = true;
        }
        if (null != taskBody.getWorkMode()  &&taskBody.getWorkMode() != extTaskMessage_base.getWorkMode()) {
            extTaskMessage_base.setWorkMode(taskBody.getWorkMode());
            isUpdate = true;
        }
        if (null != taskBody.getLabel() ) {
            extTaskMessage_base.setLabel(taskBody.getLabel());
            isUpdate = true;
        }
        Boolean isOK = false;
        if (userid.equals(extTaskMessage_base.getFromUser()))
            isOK = true;
        if (!isOK) {
            if (extTaskMessage_base.getExtTaskUser().size() > 0)
                for (ExtTaskUser extTaskUser : extTaskMessage_base.getExtTaskUser()) {
                    if (extTaskUser.getTaskUser().equals(userid))
                        isOK = true;
                }
        }
        if (!isOK) {
            throw new StatusException(401, "无权进行此次操作");
        }
        if (null != taskBody.getStatus() && taskBody.getStatus() != extTaskMessage_base.getStatus()) {
            extTaskMessage_base.setOld(true);
            extTaskMessage_base.setStatus(null != taskBody.getStatus() ? taskBody.getStatus() : extTaskMessage_base.getStatus());
            if(extTaskMessage_base.getStatus()==TaskStatus.FINISHED || extTaskMessage_base.getStatus()==TaskStatus.REFUSE){
            	extTaskMessage_base.setFinishTime(new Date());
            }
            if(extTaskMessage_base.getStatus()==TaskStatus.OVER){
            	extTaskMessage_base.setCloseTime(new Date());
            }
            isUpdate = true;
        }

        if (isUpdate) {

            extTaskMessage_base.setIos(serviceIosUrl+"&taskId="+uuid);
            extTaskMessage_base.setUrl(serviceUrl+"&taskId="+uuid);
            extTaskMessage_base.setAndroid(serviceAndroidUrl+"&taskId="+uuid);
            if(extTaskMessage_base.getStatus().equals(TaskStatus.DELETE)){
                extTaskMessage_base.setIos(null);
                extTaskMessage_base.setUrl(null);
                extTaskMessage_base.setAndroid(null);
            }


            if(extTaskMessage_base.isOld()){
                extTaskMessage_base = route.preUpadeStatusExtTaskMessage(extTaskMessage_base);
            }else{
                extTaskMessage_base = route.upadeContentSendExtTaskMessage(extTaskMessage_base);
            }
            extTaskMessageRepository.save(extTaskMessage_base);
        }

        return extTaskMessage_base;
    }

    @Override
    public PageDTO<ExtTaskMessage> findAll(MessageQuery query) {
        if(null == query)
            return null;
//        添加搜索记录
        if (0 == query.search_type && StringUtils.isNotEmpty(query.keyword)) {
            try {
                extTaskSearchHistoryService.add(query.userId, query.keyword);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        PageDTO<ExtTaskMessage> page = extTaskMessageDao.findAllPage(query);
        return page;
    }

    @Override
    public PageDTO<TotalLookDTO> findLookAll(MessageQuery query) {
        PageDTO<TotalLookDTO> pageDTO = extTaskMessageDao.findLookAllPage(query);
        return pageDTO;
    }

    @Override
    public Page<ExtTaskMessageHistory> findContentAll(MessageQuery messageQuery) {
        ExtTaskMessage extTaskMessage = extTaskMessageRepository.findByUuid(messageQuery.msgUUID);
        if(null == extTaskMessage)
            throw new NotFoundException();
        Specification<ExtTaskMessageHistory> specification = new Specification<ExtTaskMessageHistory>() {
            @Override
            public Predicate toPredicate(Root<ExtTaskMessageHistory> root,
                                         CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> predicates = new ArrayList<>();
                    predicates.add(criteriaBuilder.equal(root.get("messageId"), extTaskMessage.getId()));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };

        Sort sort = new Sort(Sort.Direction.ASC, "createTime");
        Pageable pageable = new PageRequest(messageQuery.page, messageQuery.size, sort);
        Page<ExtTaskMessageHistory> page = extTaskMessageHistoryRepository.findAll(specification, pageable);
        return page;
    }

    @Override
    public ViewTotalDTO count(MessageQuery messageQuery) {
        ViewTotalDTO dto = extTaskMessageDao.count(messageQuery);
        return dto;
    }

    @Override
    @Transactional
    public void addContent(MessageQuery messageQuery, String content, Integer source) {
        if(null == messageQuery || StringUtils.isEmpty(messageQuery.group) ||
                StringUtils.isEmpty(messageQuery.userId) ||
                StringUtils.isEmpty(messageQuery.userName))
            return;

        PageDTO<ExtTaskMessage> messagePage = this.findAll(messageQuery, null);
        if(null == messagePage || messagePage.elements.size() == 0)
            return;
        List<ExtTaskMessageHistory> histories = new LinkedList<>();
        ExtTaskMessageHistory history = null;
        for(ExtTaskMessage message : messagePage.elements){
            message.setSource(source);
            message.setContextFlag(message.getContextFlag() + 1);

            history = new ExtTaskMessageHistory();
            history.setMessageId(message.getId());
            history.setTaskUser(messageQuery.userId);
            history.setTaskUserName(messageQuery.userName);
//            todo 添加微信验证及赋值
            history.setContent(content);
            history.setCreateTime(new Timestamp(System.currentTimeMillis()));
            histories.add(history);
        }
        extTaskMessageRepository.save(messagePage.elements);
        extTaskMessageHistoryRepository.save(histories);
    }

    private void  setRole(String userid,ExtTaskMessage rt){
        if(userid.equals(rt.getFromUser())){
            rt.setRole("author");
            return;
        }
        if(null != rt.getExtTaskUser() && rt.getExtTaskUser().size() > 0)
        for(ExtTaskUser extTaskUser : rt.getExtTaskUser()){
            if(userid.equals(extTaskUser.getTaskUser())){
                rt.setRole("executor");
                return;
            }
        }
    }

    private void  setStatus(String userid,ExtTaskMessage rt){
        if(rt.getStatus().equals(TaskStatus.OVER)) {
            rt.setStatus(TaskStatus.OVER);
            return;
        }
        if(userid.equals(rt.getFromUser())){
           return;
        }
        for(ExtTaskUser extTaskUser : rt.getExtTaskUser()){
            if(userid.equals(extTaskUser.getTaskUser())){
                rt.setStatus(extTaskUser.getStatus());
            }
        }
    }
}
